import ast
import json
import os
import subprocess
import cv2 as cv
import numpy as np
import pandas as pd
from skimage.metrics import structural_similarity
from scripts_env.paint_area import paint_rect
from scripts_env.info import Base_Info


def create_path(path):
    is_exists = os.path.exists(path)
    if not is_exists:
        os.makedirs(path)


def run_cmd(cmd):
    ret = subprocess.getoutput(cmd)
    return ret


def save_json(file_name, data: dict):
    json_str = json.dumps(data, indent=4, ensure_ascii=False)
    with open(file_name, 'w') as json_file:
        json_file.write(json_str)


def count_file(path, suffix):
    number = 0
    if os.path.exists(path):
        for _, _, filenames in os.walk(path):
            for filename in filenames:
                if os.path.splitext(filename)[1] == suffix:
                    number += 1
    return number


def find_file(path, suffix):
    number = 0
    file_path = []
    if os.path.exists(path):
        for root, dirs, filenames in os.walk(path):
            for filename in filenames:
                if os.path.splitext(filename)[1] == suffix:
                    number += 1
                    file_path.append(os.path.join(root, filename))
    return file_path


def get_roi_mat(image, data, step):
    df = pd.read_csv(data, index_col=0)
    if '比对区域' not in df.columns.to_list():
        df.columns.to_list().insert(4, '比对区域')
        df.reindex(columns=df.columns.to_list())
        df.insert(loc=4, column='比对区域', value='')
    if '相似度' not in df.columns.to_list():
        df.columns.to_list().insert(5, '相似度')
        df.reindex(columns=df.columns.to_list())
        df.insert(loc=5, column='相似度', value='nan')
    if '结果' not in df.columns.to_list():
        df.columns.to_list().insert(6, '结果')
        df.reindex(columns=df.columns.to_list())
        df.insert(loc=6, column='结果', value='nan')
        df.to_csv(data, columns=df.columns.to_list(), encoding='utf_8_sig')
    df['比对区域'] = df['比对区域'].astype('object')
    roi = df.at[int(step), '比对区域']
    img = cv.imread(image, cv.IMREAD_GRAYSCALE)
    img = cv.GaussianBlur(img, (1, 1), 0)
    img_w = img.shape[0]
    img_h = img.shape[1]
    if not pd.isna(roi):
        area_pos = ast.literal_eval(roi)
        min_x = area_pos[0][0]
        min_y = area_pos[0][1]
        width = abs(area_pos[0][0]-area_pos[1][0])
        height = abs(area_pos[0][1]-area_pos[1][1])
        roi_mat = img[min_y:min_y+height, min_x:min_x+width]
        # cv.imwrite(str(step)+"select-area-image.png", roi_mat)
        return roi_mat
    else:
        # # cv.imwrite("desktop.png", img[120:int(img_w)-40, 0:img_h])
        # ret = imnore_area(img)
        # if ret <= 0.4:
        #     res = img[0:int(img_w)-40, 0:img_h]
        #     # cv.imwrite("ignore1.png",res)
        #     return res
        # else:
        #     res = img[0:int(img_w)-40, 120:img_h]
        #     # cv.imwrite("ignore2.png",res)
        #     return res
        return img[0:int(img_w)-40, 0:img_h]


def imnore_area(src):
    ignore = cv.imread('/opt/lance/ignore.png', cv.IMREAD_GRAYSCALE)
    h, w = ignore.shape[:2]
    methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
               'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']
    res = cv.matchTemplate(src, ignore, cv.TM_SQDIFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
    print(min_val, max_val, min_loc, max_loc)
    top_left = list(min_loc)
    find_img = src[top_left[1]:top_left[1]+h, top_left[0]:top_left[0]+w]
    if ignore.shape[0] < 5 or ignore.shape[1] < 5:
        ignore = cv.resize(ignore, (7, 7))
    if find_img.shape[0] < 5 or find_img.shape[1] < 5:
        find_img = cv.resize(find_img, (7, 7))
    score, _ = structural_similarity(
        im1=ignore, im2=find_img, win_size=3, gaussian_weights=True, full=True)  # , K1=0.1, K2=0.1)
    return score


def to_gray(image):
    img = cv.imread(image, 1)
    gray_image = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    return gray_image


def paint_roi(data, image_path):
    if os.path.exists(data):
        paint_rect(data, image_path)


def update_result(data_path, confidence, replay_image_path):
    df = pd.read_csv(data_path, index_col=0)
    df["相似度"] = ''
    df["结果"] = ''
    for k, v in confidence.items():
        df.iloc[int(k)-1, 5] = v
        if v == -1:
            df.iloc[int(k)-1, 6] = '错误'
        elif -1 < float(v) < 0.985:
            df.iloc[int(k)-1, 6] = '失败'
        elif float(v) >= 0.985:
            df.iloc[int(k)-1, 6] = '通过'
    replay_data_path = os.path.join(
        replay_image_path.split('runtime_image')[0], data_path.split('/')[-1])
    df.to_csv(replay_data_path, encoding='utf_8_sig')
    # paint_roi(replay_data_path, replay_image_path)
    info = Base_Info()
    env_info = os.path.join(
        replay_image_path.split('runtime_image')[0], '测试环境信息')
    save_json(env_info, info.base_info())
    print("比对结果:", confidence)


def sim_compare(expect_image_path, replay_image_path, data_path, image_name, algo):
    confidence = {}
    for i in image_name:
        source = os.path.join(expect_image_path, i)
        dest = os.path.join(replay_image_path, i)
        if os.path.exists(source) and os.path.exists(dest):
            except_img = cv.imread(source)
            replay_img = cv.imread(dest)
            expect_w = except_img.shape[0]
            except_h = except_img.shape[1]
            replay_w = replay_img.shape[0]
            replay_h = replay_img.shape[1]
            if expect_w == replay_w and except_h == replay_h:
                step = int(i.split('.png')[0])
                except_roi = get_roi_mat(source, data_path, step)
                run_roi = get_roi_mat(dest, data_path, step)
                if except_roi.shape[0] < 5 or except_roi.shape[1] < 5:
                    except_roi = cv.resize(except_roi, (7, 7))
                if run_roi.shape[0] < 5 or run_roi.shape[1] < 5:
                    run_roi = cv.resize(run_roi, (7, 7))
                score, _ = structural_similarity(
                    im1=except_roi, im2=run_roi, win_size=3, gaussian_weights=True, full=True)
                index = str(i).split('.')[0]
                confidence.update({index: round(score, 4)})
            else:
                index = str(i).split('.')[0]
                confidence.update({index: -1})
    update_result(data_path, confidence, replay_image_path)
